package com.tronsis.library.http;


import android.app.Activity;
import android.text.TextUtils;


import com.tronsis.library.Constants;
import com.tronsis.library.util.LogUtil;
import com.tronsis.library.util.SharedPreferencesUtil;
import com.tronsis.library.util.StringUtil;

import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okio.Buffer;

/**
 * RequestClient
 *
 * @author allen@tronsis.com
 */
public class RequestClient {
    private OkHttpClient mOkHttpClient;
    private RequestBody mRequestBody; // http请求体
    private HttpCallBack mCallBack;
    private String mHttpParamsUrl;
    private String mAuthorization;
    private String mHostPort;
    private Activity mActivity;

    private RequestClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(HttpConfig.MAX_CONNECT_TIMEOUT, TimeUnit.SECONDS);
        builder.readTimeout(HttpConfig.MAX_READ_TIMEOUT, TimeUnit.SECONDS);
        builder.writeTimeout(HttpConfig.MAX_WRITE_TIMEOUT, TimeUnit.SECONDS);
        builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(new InputStream[]{new Buffer().writeUtf8(HttpConfig.SERVER_CERTIFICATE)
         .inputStream()
                }, null, null);
        builder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
        this.mOkHttpClient = builder.build();
    }

    public static RequestClient getInstance(HttpCallBack callback) {
        SingletonHolder.requestClient.init(callback);
        return SingletonHolder.requestClient;
    }

    /**
     * 用于单例模式
     *
     * @author allen@tronsis.com
     */
    private static class SingletonHolder {
        public static RequestClient requestClient = new RequestClient();
    }

    private void init(HttpCallBack callback) {
        this.mCallBack = callback;
        mActivity = callback.getActivity();
        if (mActivity != null) {
            mAuthorization = SharedPreferencesUtil.getString(mActivity.getApplicationContext(), Constants.SP_HEADER_AUTHORIZATION, null);
            LogUtil.i("RequestClient-init", "Authorization: " + mAuthorization);
        }

    }

    /**
     * POST
     * 添加需提交的参数对（值为null的参数对不予提交）
     *
     * @param params 参数对
     * @return 当前对象
     * @throws Exception
     */
    public RequestClient addParameter(String... params) throws Exception {
        FormBody.Builder builder = new FormBody.Builder();

        if (params != null) {
            if (params.length % 2 != 0) {
                throw new Exception("The length of the variable parameter is not even.");
            }

            for (int i = 0; i < params.length; i++) {
                if (TextUtils.isEmpty(params[i])) {
                    throw new Exception("The variable parameter is empty.");
                }
                String params2 = params[i + 1];
                if (params2 != null) {
                    builder.add(params[i], params2);
                    LogUtil.e("params" + i, params[i] + ": " + params2);
                }
                i++;
            }
        }

        mRequestBody = builder.build();

        return this;
    }

    /**
     * 添加FROM提交参数（值为null的参数对不予提交）
     *
     * @param fileParamName 文件参数名
     * @param fileList      文件
     * @param params        其它参数对
     * @throws Exception
     */
    public RequestClient addFormParameter(String fileParamName, List<File> fileList, String... params) throws Exception {
        MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();

        multipartBodyBuilder.setType(MultipartBody.FORM);

        if (fileList != null) {
            for (int i = 0; i < fileList.size(); i++) {
                File file = fileList.get(i);
                if (file == null) {
                    continue;
                }
                // 文件类型，可根据实际情况设置
                RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), file);
                if (file.getAbsolutePath().endsWith(".mp4")) {
                    fileBody = RequestBody.create(MediaType.parse("video/mp4"), file);
                }
                multipartBodyBuilder.addFormDataPart(fileParamName, file.getName(), fileBody);
            }
        }

        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                if (TextUtils.isEmpty(params[i])) {
                    throw new Exception("The variable parameter is empty.");
                }
                String params2 = params[i + 1];
                if (params2 != null) {
                    multipartBodyBuilder.addFormDataPart(params[i], params2);
                    LogUtil.e("params" + i, params[i] + ": " + params2);
                }
                i++;
            }
        }

        mRequestBody = multipartBodyBuilder.build();
        return this;
    }


    /**
     * post 提交json
     */
    public RequestClient addJsonParameter(String json) throws Exception {
        mRequestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        LogUtil.e("post_json : mRequestBody", json);
        return this;
    }

    /**
     * 执行http请求
     *
     * @param method    http请求方式
     * @param actionUrl 请求的action的相对路径
     */
    public void excute(RequestMethod method, String actionUrl) {
        if (TextUtils.isEmpty(actionUrl)) {
            LogUtil.w("HttpRequest", "Empty url");
            return;
        }
        switch (method) {
            case POST: // post请求
                LogUtil.w("Request Method", "POST");
                post(actionUrl);
                break;

            case GET: // Get请求
                LogUtil.w("Request Method", "GET");
                get(actionUrl + mHttpParamsUrl);
                break;

            case PUT:
                LogUtil.w("Request Method", "PUT");
                put(actionUrl + mHttpParamsUrl);
                break;

            case DELETE:
                LogUtil.w("Request Method", "DELETE");
                delete(actionUrl + mHttpParamsUrl);
                break;

            case POST_JSON:
                LogUtil.w("Request Method", "post_json");
                postJson(actionUrl);
                break;

            case PATCH:
                LogUtil.w("Request Method", "PATCH");
                patch(actionUrl);
                break;
            case PUT_JSON:
                LogUtil.w("Request Method", "PUT_JSON");
                putJson(actionUrl + mHttpParamsUrl);
                break;
            default:
                break;
        }
    }

    private Request.Builder getRequestBuilder() {
        Request.Builder requestBuilder = new Request.Builder();
        requestBuilder.addHeader(HttpConfig.HTTP_HEADER_NAME_UA, HttpConfig.HTTP_HEADER_VALUE_UA);
        if (mAuthorization != null) {
            requestBuilder.addHeader(HttpConfig.HTTP_HERDER_NAME_AUTH, mAuthorization);
        }
        if (mHostPort != null) {
            requestBuilder.addHeader(HttpConfig.HTTP_HEADER_KEY_HOST, StringUtil.md5(mHostPort));
        }
        return requestBuilder;
    }

    /**
     * GET请求
     *
     * @param url
     */
    private void get(String url) {
        LogUtil.w("HTTP URL FULL", url);
        // 创建一个Request
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url);

        Request request = requestBuilder.build();
        Call call = mOkHttpClient.newCall(request);
        // 请求加入调度
        call.enqueue(mCallBack);
        mCallBack.onStart();
    }

    /**
     * POST请求
     *
     * @param url
     */
    private void post(String url) {
        LogUtil.w("HTTP URL FULL", url);
        if (mRequestBody != null) {
            LogUtil.w("HTTP request body", mRequestBody.toString());
        }
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url).post(mRequestBody);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(mCallBack);
        mCallBack.onStart();
    }

    /**
     * PUT请求
     *
     * @param url
     */
    private void put(String url) {
        LogUtil.w("HTTP URL FULL", url);
        FormBody.Builder builder = new FormBody.Builder();
        mRequestBody = builder.build();
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url).put(mRequestBody);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(mCallBack);
        mCallBack.onStart();
    }

    /**
     * DELETE请求
     *
     * @param url
     */
    private void delete(String url) {
        LogUtil.w("HTTP URL FULL", url);
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url).delete(mRequestBody);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(mCallBack);
        mCallBack.onStart();
    }

    private void patch(String url) {
        LogUtil.w("HTTP URL FULL", url);
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url).patch(mRequestBody);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(mCallBack);
        mCallBack.onStart();
    }

    private void postJson(String url) {
        LogUtil.w("HTTP URL FULL", url);
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url).post(mRequestBody);
        requestBuilder.addHeader(HttpConfig.HTTP_HEADER_NAME_CONTENT_TYPE, HttpConfig.HTTP_HEADER_VALUE_CONTENT_TYPE);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(mCallBack);
        mCallBack.onStart();
    }

    private void putJson(String url) {
        LogUtil.w("HTTP URL FULL", url);
        Request.Builder requestBuilder = getRequestBuilder();
        requestBuilder.url(url).put(mRequestBody);
        requestBuilder.addHeader(HttpConfig.HTTP_HEADER_NAME_CONTENT_TYPE, HttpConfig.HTTP_HEADER_VALUE_CONTENT_TYPE);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(mCallBack);
        mCallBack.onStart();
    }


    /**
     * get,put,delete请求参数
     *
     * @param params null代表不拼接参数, ""代表参数为空串
     * @return
     * @throws Exception
     */
    public RequestClient addGetParams(String... params) throws Exception {
        mHttpParamsUrl = "";
        StringBuffer stringBuffer = new StringBuffer();
        if (params != null && params.length > 0) {
            if (params.length % 2 != 0) {
                throw new Exception("The length of the variable parameter is not even.");
            }
            stringBuffer.append("?");
            for (int i = 0; i < params.length; i = i + 2) {
                if (TextUtils.isEmpty(params[i])) {
                    throw new Exception("The variable parameter is empty.");
                }

                if (i != 0 && params[i + 1] != null) {
                    stringBuffer.append("&");
                }

                if (params[i + 1] != null) {
                    stringBuffer.append(params[i] + "=" + URLEncoder.encode(params[i + 1], "utf-8"));
                    LogUtil.e("params" + i, params[i] + ": " + params[i + 1]);
                }
            }
        }
        mHttpParamsUrl = stringBuffer.toString();
        return this;
    }

}
